Mario - CS50x 2023
入门
打开 VS Code。
首先,点击你的终端窗口内部,然后单独执行 cd
。 你会看到如下所示的提示符。
点击终端窗口内部,然后执行
wget https://cdn.cs50.net/2022/fall/psets/1/mario-less.zip
然后按回车键,就可以在你的 codespace 中下载一个名为 mario-less.zip
的 ZIP 文件了。 务必注意 wget
和后面的 URL 之间的空格,以及任何其他字符!
现在执行
来创建一个名为 mario-less
的文件夹。 你现在不需要这个 ZIP 文件了,所以可以执行
并在提示符后输入“y”,然后按回车键,删除你下载的 ZIP 文件。
现在输入
然后按回车键,进入(或者说打开)该目录。 现在你的提示符应该类似下面这样。
如果一切顺利,你应该执行
并看到一个名为 mario.c
的文件。 执行 code mario.c
应该会打开该文件,你将在其中输入此问题集的代码。 如果不是,请检查一下你的步骤,看看哪里出错了!
世界 1-1
在任天堂的《超级马里奥兄弟》游戏里,第一大关 1-1 的结尾部分,马里奥需要爬上一个右对齐的积木金字塔,就像下图展示的那样。
让我们用 C 语言,以文本的形式,使用井号 (#
) 来代表砖块,重建这个金字塔,就像下面这样。 每个井号都比它的宽度稍高,所以金字塔本身也会比它的宽度更高。
#
##
###
####
#####
######
#######
########
我们编写的程序会叫做 mario
。 我们让用户来决定金字塔的高度,首先提示他们输入一个 1 到 8 之间的正整数(包括 1 和 8)。
如果用户在提示时输入 8
,程序可能会这样运行:
$ ./mario
Height: 8
#
##
###
####
#####
######
#######
########
如果用户在提示时输入 4
,程序可能会这样运行:
$ ./mario
Height: 4
#
##
###
####
如果用户在提示时输入 2
,程序可能会这样运行:
如果用户在提示时输入 1
,程序可能会这样运行:
如果用户没有输入 1 到 8 之间的正整数(包括 1 和 8),程序应该不断提示用户重新输入,直到输入正确为止。
$ ./mario
Height: -1
Height: 0
Height: 42
Height: 50
Height: 4
#
##
###
####
如何开始? 让我们一步一步地解决这个问题。
演练
伪代码
首先,执行
确保你位于 codespace 的默认目录。
然后,执行
进入你的 mario-less
目录。
然后,执行
来打开该目录中名为 pseudocode.txt
的文件。
在 pseudocode.txt
中编写一些伪代码来实现这个程序,即使你还不确定如何用代码来实现。伪代码的写法没有定式,用简短的语句描述即可。不妨回顾一下,我们之前是如何用伪代码来描述在电话簿中查找联系人的过程。你的伪代码可能会用到函数、条件语句、布尔表达式、循环和变量等概念。
提示
实现方法不止一种,这里只是一种!
- 提示用户输入高度
- 如果高度小于 1 或大于 8,或者不是整数,则返回上一步
- 从 1 迭代到高度:
- 在第 i 次迭代时,打印 i 个 '#' 符号并换行
可以参考这里的伪代码,但请勿直接复制粘贴!
提示输入
无论你的伪代码如何,我们先编写C代码来提示用户输入(并在必要时重复提示)。打开 mario
目录下的 mario.c
文件 (提示:回顾之前的步骤).
现在,修改 mario.c
,使其提示用户输入金字塔的高度,并将输入存储在一个变量中。如果用户输入的不是1到8之间的正整数,程序需要重复提示用户输入. 然后,打印该变量的值,以确认你已成功存储用户的输入,如下所示。
$ ./mario
Height: -1
Height: 0
Height: 42
Height: 50
Height: 4
Stored: 4
提示
- 记得可以使用
make
命令编译程序. - 回想一下,你可以使用
printf
和%i
打印一个int
。 - 回想一下,你可以使用
get_int
从用户那里获取一个整数。 - 回想一下,
get_int
在cs50.h
中声明。 - 回想一下,我们在讲座中使用
do while
循环在mario.c
中提示用户输入一个正整数。
构建反向金字塔
现在,如果你的程序能够正确接收输入,就可以进行下一步了。
如你所见,构建左对齐的金字塔比右对齐的要简单一些.
修改 mario.c
文件,使其不再只是打印用户的输入,而是打印一个对应高度的左对齐金字塔。
提示
请记住,井号(
#
)也只是一个普通字符,因此可以使用printf
函数打印。正如 Scratch 拥有
repeat
积木块一样,C 语言也提供了for
循环,允许你重复执行代码块多次。也许在每次循环迭代中,你可以打印相应数量的井号?实际上,你可以“嵌套”循环,即在一个“外部”循环中使用变量(例如
i
)进行迭代,并在其“内部”循环中使用另一个变量(例如j
)进行迭代。例如,以下代码展示了如何打印一个高度和宽度均为n
的正方形。当然,本次练习的目标并非打印正方形!for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
printf("#");
}
printf("\n");
}
用点号右对齐
现在,我们将在井号前添加点号(.
,即句点符号)来右对齐金字塔,效果如下所示。
.......#
......##
.....###
....####
...#####
..######
.#######
########
修改 mario.c
,使其完全按照上述方式执行!
提示
请注意,每行所需点号的数量与该行井号的数量存在一种“互补”关系。对于高度为 8 的金字塔(如上图),第一行只有一个井号,因此有 7 个点。同时,底行有 8 个井号,因此有 0 个点。通过什么公式(或者说算术),你可以打印出那么多的点?
如何测试你的代码
当输入以下数值时,你的代码是否能按预期运行?
-1
(或其他负数)?0
?1
到8
?9
或其他正数?- 字母或单词?
- 如果未输入任何内容,直接按下回车键,程序是否能正确处理?
移除点号
现在剩下的只是最后的润色!修改 mario.c
,使其打印空格而不是那些点号!
如何测试你的代码
执行以下命令以使用 check50
评估代码的正确性。但请务必自己编译并测试它!
check50 cs50/problems/2023/x/mario/less
执行以下命令以使用 style50
评估代码的风格。
提示
空格字符可以通过敲击空格键输入,句点字符则通过敲击句点键输入!请记住,printf
要求您用双引号将它们括起来!
如何提交
在您的终端中,执行以下命令以提交您的工作。
submit50 cs50/problems/2023/x/mario/less